package jokode

import (
	"fmt"
	"io"
	"os"
	"time"
)

type StdLogger struct{}

func (l *StdLogger) Debug(args ...any) {
	go stdLoggerPrintln(LogLevelDebug, args...)
}

func (l *StdLogger) Info(args ...any) {
	go stdLoggerPrintln(LogLevelInfo, args...)
}

func (l *StdLogger) Warn(args ...any) {
	go stdLoggerPrintln(LogLevelWarn, args...)
}

func (l *StdLogger) Error(args ...any) {
	go stdLoggerPrintln(LogLevelError, args...)
}

func (l *StdLogger) Fatal(args ...any) {
	go stdLoggerPrintln(LogLevelFatal, args...)
}

func (l *StdLogger) Debugf(format string, args ...any) {
	go stdLoggerPrintlnF(LogLevelDebug, format, args...)
}

func (l *StdLogger) Infof(format string, args ...any) {
	go stdLoggerPrintlnF(LogLevelInfo, format, args...)
}

func (l *StdLogger) Warnf(format string, args ...any) {
	go stdLoggerPrintlnF(LogLevelWarn, format, args...)
}

func (l *StdLogger) Errorf(format string, args ...any) {
	go stdLoggerPrintlnF(LogLevelError, format, args...)
}

func (l *StdLogger) Fatalf(format string, args ...any) {
	go func() {
		stdLoggerPrintlnF(LogLevelFatal, format, args...)
		os.Exit(1)
	}()
}

func (l *StdLogger) Sync() error {
	return nil
}

func stdLoggerPrintln(level LogLevel, args ...any) {
	ti := time.Now()
	fi := getStdLoggerWriter(level)

	_, _ = fmt.Fprintf(fi, "%s [%s] ", ti.Format(DefTimeFormatMs), level)
	_, _ = fmt.Fprintln(fi, args...)
}

func stdLoggerPrintlnF(level LogLevel, format string, args ...any) {
	ti := time.Now()
	fi := getStdLoggerWriter(level)

	_, _ = fmt.Fprintf(fi, "%s [%s] ", ti.Format(DefTimeFormatMs), level)
	_, _ = fmt.Fprintf(fi, format, args...)
	_, _ = fmt.Fprintln(fi)
}

func getStdLoggerWriter(level LogLevel) io.Writer {
	if level < LogLevelError {
		return os.Stdout
	} else {
		return os.Stderr
	}
}
